#ifndef SCENE_H
#define SCENE_H

#include <QGraphicsScene>
#include <QGraphicsSceneEvent>
#include <QGraphicsView>
#include <QDebug>
#include <QGraphicsItem>
#include <QMenu>
#include <QRubberBand>
#include <QStyle>
#include <QMessageBox>
#include <QTransform>
#include <QBitmap>

#include "config.h"
//#include "image.h"
#include "sessionmanager.h"
#include "imagepart.h"



/**************************************************************************************************/
class BasicScene : public QGraphicsScene
{
    Q_OBJECT

public:
    BasicScene (QObject * parent = 0);
    void wheelEvent (QGraphicsSceneWheelEvent * wheelEvent);
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void incrZoomBy (const qreal z);
    void setZoomOriginal ();
    void setZoomBestFit(const QImage &image);
    qreal zoom ();

public slots:
    void setZoom (const qreal z);

signals:
    void zoomed (const qreal z);
};


/**************************************************************************************************/
class Scene : public BasicScene
{
    Q_OBJECT

public:
    Scene (QGraphicsPixmapItem* previewItem);

    void mousePressEvent (QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent (QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent (QGraphicsSceneMouseEvent *event);
    void contextMenuEvent (QGraphicsSceneContextMenuEvent *event);
    void mouseDoubleClickEvent (QGraphicsSceneMouseEvent * event);
    void keyReleaseEvent(QKeyEvent *event);

public slots:
    void onCreatePartsFrom (const QList<QRect> &redList, const QList<QRect> &greenList);
    void onChanged (const QList<QRectF>& region);
    void clear ();

    void setPreviewPixmap (const QPixmap &preview);
    void setOriginalPixmap (const QPixmap &original);
    void setPdf (bool b) { m_pdf = b; }

signals:
    void rectsHaveChanged (const QList<QRect> &redList, const QList<QRect> &greenList);
    void askInformationsAboutCurrentImage ();
    void askOCRFrom (ImagePart* part);
    void askExtractionFrom (const QRectF &rectF);
    void askPartSettingsOf (ImagePart *part);

private:
    QGraphicsPixmapItem* m_pixmapItem;
    QGraphicsPixmapItem* m_previewItem;
    QGraphicsScene *m_previewScene;
    void setPreviewPixmapItem (QGraphicsPixmapItem* pixmapItem) { m_previewItem = pixmapItem; }
    bool m_pdf;
    bool isPdf () { return m_pdf; }
    int m_mode;
    int mode () { return m_mode; }
    void setMode (const int newMode);
    enum { NoAction, CreatingPart, MovingParts, ResizingPart };

    QList<ImagePart*> m_partList;
    QList<ImagePart*> greenList ();
    QList<ImagePart*> redList ();

    QList<QRect> toRedRects () {
        QList<QRect> result;
        foreach (const ImagePart *red, redList ()) {
            result << red->rectangle ();
        }
        return result;
    }
    QList<QRect> toGreenRects () {
        QList<QRect> result;
        foreach (const ImagePart *green, greenList ()) {
            result << green->rectangle ();
        }
        return result;
    }

    int nextPartOrder ();
    void removePart (const int index);
    void removePart (ImagePart *part);
    void removeAllParts ();
    void removeSelectedParts ();
    void selectAllParts ();
    void unSelectAllParts () { clearSelection (); }

    QGraphicsItemGroup* m_partGroup;

    QPointF m_movingStartDeltaPos;
    QPointF m_creatingStartScreenPos;
    QPointF m_creatingStartScenePos;

    ImagePart* addPart (const QRect &r);
    void startMovingParts (const QPointF& scenePos, const QPointF& pos);
    void movingParts (const QPointF& pos);
    void endMovingParts ();
    void startCreatingPart (const QPointF& screenPos, const QPointF& pos);
    void creatingPart(const QPointF& screenPos);
    void endCreatingPart (const QPointF& scenePos);
    ImagePart* partAt (const QPointF& scenePos);
    QRubberBand* m_rubber;
    void setFirstPart(ImagePart *part);
    void setLastPart(ImagePart *part);
    void swapPartOrder(ImagePart *part1, const int newOrder);
    int lastPartOrder () { return greenList ().size (); }
    bool m_canUpdateParts;
    void canUpdateParts (bool b) { if (m_canUpdateParts != b) m_canUpdateParts = b; }
    bool canUpdateParts () { return m_canUpdateParts; }
    void updateParts ();

    QGraphicsItem* itemClicked (const QPointF &pos) { return itemAt (pos, QTransform ()); }

    void contextMenu (ImagePart* part);
    void contextMenu (QGraphicsPixmapItem *pi);
    void setNextRole(ImagePart *part);

    void setRotate (const qreal angle);

};


#endif // SCENE_H
